﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using Moonlite.Platform.General;
namespace Moonlite.Services.Web.Rss
{
    public partial class RssViewControl : Control
    {
        private const int MaxItemHeight = 100;
        private const string FeedUrl = "http://www.vestras.net/moonlite/news/moonlite-rss-feed.xml";
        public RssFeed Feed { get; set; }
        private bool IsMouseDown { get; set; }
        private bool IsMouseOverAnyLink { get; set; }
        private string CurrentLink { get; set; }
        private VScrollBar VScrollBar { get; set; }
        private int FirstItem { get; set; }
        private int MaxListLength
        {
            get { return Height / MaxItemHeight; }
        }

        private Color dateColor = Color.Gray;
        public Color DateColor
        {
            get { return dateColor; }
            set { dateColor = value; }
        }

        private Font captionFont = new Font("Segoe UI", 12f);
        public Font CaptionFont
        {
            get { return captionFont; }
            set { captionFont = value; }
        }

        private Font dateFont = new Font("Segoe UI", 10f);
        public Font DateFont
        {
            get { return dateFont; }
            set { dateFont = value; }
        }

        private FontStyle hoverFontStyle = FontStyle.Underline;
        public FontStyle HoverFontStyle
        {
            get { return hoverFontStyle; }
            set { hoverFontStyle = value; }
        }

        private Color linkColor = Color.Blue;
        public Color LinkColor
        {
            get { return linkColor; }
            set { linkColor = value; }
        }

        private Color hoverColor = Color.DodgerBlue;
        public Color HoverColor
        {
            get { return hoverColor; }
            set { hoverColor = value; }
        }

        private Color clickColor = Color.CornflowerBlue;
        public Color ClickColor
        {
            get { return clickColor; }
            set { clickColor = value; }
        }

        private int itemMargin = 8;
        public int ItemMargin
        {
            get { return itemMargin; }
            set { itemMargin = value; }
        }

        private void PaintError(PaintEventArgs e)
        {
            string errorMessage = String.Format("An error occured while processing the Rss feed: {0}{1}", Environment.NewLine, Feed.ErrorMessage);
            SizeF textSize = e.Graphics.MeasureString(errorMessage, Font);
            Rectangle textBounds = new Rectangle(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width, (int)textSize.Height);
            using (StringFormat format = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center })
            {
                using (SolidBrush brush = new SolidBrush(ForeColor))
                {
                    e.Graphics.DrawString(errorMessage, Font, brush, textBounds, format);
                }
            }
        }

        private int PaintItem(PaintEventArgs e, RssItem item, int y)
        {
            SizeF dateSize = e.Graphics.MeasureString(item.PublishDate, DateFont);
            SizeF headerSize = e.Graphics.MeasureString(item.Title, CaptionFont, ClientSize.Width - (int)dateSize.Width);
            SizeF contentSize = e.Graphics.MeasureString(item.Description, Font, ClientSize.Width);
            Rectangle dateBounds = new Rectangle(ClientSize.Width - (int)dateSize.Width + 1 - SystemInformation.VerticalScrollBarWidth, y, (int)dateSize.Width + 1, (int)dateSize.Height);
            Rectangle headerBounds = new Rectangle(0, y, (int)headerSize.Width + 1, (int)headerSize.Height);
            Rectangle contentBounds = new Rectangle(0, y + (int)headerSize.Height + 3, (int)contentSize.Width + 1, (int)contentSize.Height);
            using (SolidBrush brush = new SolidBrush(DateColor))
            {
                e.Graphics.DrawString(item.PublishDate, DateFont, brush, dateBounds);
            }

            using (SolidBrush brush = new SolidBrush(ForeColor))
            {
                string text = headerBounds.Height + contentBounds.Height + 3 > MaxItemHeight ? item.Description.Substring(0, 30) + "(...)" : item.Description;
                contentSize = e.Graphics.MeasureString(text, Font, ClientSize.Width);
                e.Graphics.DrawString(text, Font, brush, contentBounds);
            }

            bool mouseOver = IsMouseOverLink(headerBounds);
            Color linkBrushColor = mouseOver && !IsMouseDown ? HoverColor : mouseOver && IsMouseDown ? ClickColor : LinkColor;
            FontStyle fontStyle = mouseOver && !IsMouseDown ? HoverFontStyle : mouseOver && IsMouseDown ? HoverFontStyle : FontStyle.Regular;
            if (fontStyle == HoverFontStyle)
            {
                IsMouseOverAnyLink = true;
                CurrentLink = item.Link;
            }

            using (SolidBrush brush = new SolidBrush(linkBrushColor))
            {
                e.Graphics.DrawString(item.Title, new Font(CaptionFont, fontStyle), brush, headerBounds);
            }

            return (int)(headerSize.Height + contentSize.Height) + ItemMargin;
        }

        private void PaintItems(PaintEventArgs e)
        {
            int currentX = 0;
            for (int index = Math.Max(0, FirstItem); index < Feed.Items.Count; index++)
            {
                currentX += PaintItem(e, Feed.Items[index], currentX);
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            try
            {
                if (Feed.Items == null) return;
                if (string.IsNullOrEmpty(Feed.ErrorMessage) == false)
                {
                    PaintError(e);
                    return;
                }

                CurrentLink = "";
                IsMouseOverAnyLink = false;
                PaintItems(e);
            }
            catch (Exception exception)
            {
                Logger.Log += exception.Message + Environment.NewLine;
            }

            base.OnPaint(e);
        }

        protected override void OnMouseEnter(EventArgs e)
        {
            Invalidate();
            base.OnMouseEnter(e);
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            Invalidate();
            base.OnMouseLeave(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            Invalidate();
            Cursor = IsMouseOverAnyLink == true ? Cursors.Hand : Cursors.Default;
            base.OnMouseMove(e);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            IsMouseDown = true;
            if (IsMouseOverAnyLink == true)
            {
                Process.Start(CurrentLink);
            }

            Invalidate();
            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            IsMouseDown = false;
            Invalidate();
            base.OnMouseUp(e);
        }

        private bool IsMouseOverLink(Rectangle bounds)
        {
            return bounds.Contains(PointToClient(Cursor.Position));
        }

        private void OnVScrollBarValueChanged(object sender, EventArgs e)
        {
            FirstItem = VScrollBar.Value;
            Invalidate();
        }

        private void OnVScrollBarScroll(object sender, ScrollEventArgs e)
        {
            FirstItem = e.NewValue;
            Invalidate();
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            VScrollBar.LargeChange = MaxListLength;
            VScrollBar.Maximum = Feed.Items.Count - MaxListLength + 1;
            base.OnSizeChanged(e);
        }

        public RssViewControl()
        {
            InitializeComponent();
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            Feed = RssReader.GetFeed(FeedUrl);
            VScrollBar = new VScrollBar();
            VScrollBar.Dock = DockStyle.Right;
            VScrollBar.Width = SystemInformation.VerticalScrollBarWidth;
            VScrollBar.Maximum = Feed.Items.Count - MaxListLength;
            VScrollBar.LargeChange = MaxListLength;
            VScrollBar.SmallChange = 1;
            VScrollBar.ValueChanged += OnVScrollBarValueChanged;
            VScrollBar.Scroll += OnVScrollBarScroll;
            Controls.Add(VScrollBar);
            ClientSize = new Size(Width - VScrollBar.Width, Height);
            Font = new Font("Segoe UI", 10f);
        }
    }
}
